<!-- 图表设计页面 -->
<template>
  <div class="content" style="margin: 10px;">
    <el-row :gutter="15">
      <!-- 目录面板 -->
      <el-col :span="5">
        <el-card class="box-card" style="margin-bottom: 20px;" :body-style="{padding: 0}">
          <div slot="header" class="clearfix">
            <b>图表</b>
            <div style="float: right;">
              <el-button type="primary" icon="el-icon-plus" @click="addWidget" circle title="新增"></el-button>
              <el-button type="primary" icon="el-icon-delete" @click="deleteReset" circle title="删除"></el-button>
              <el-button type="primary" icon="el-icon-s-fold" circle title="折叠" @click="isShow = !isShow"></el-button>
            </div>
          </div>
          <div v-show="isShow" style="padding: 20px;">
            <el-input class="search" placeholder="输入关键字进行过滤" v-model="filterText"></el-input>
            <el-tree :data="treeData" :props="defaultProps" @node-click="handleNodeClick" :filter-node-method="filterNode" default-expand-all ref="tree"></el-tree>
          </div>
        </el-card>

        <el-card class="box-card" style="margin-bottom: 20px;" :body-style="{padding: 0}">
          <div slot="header" class="clearfix">
            <b>数据集</b>
            <div style="float: right;">
              <el-button type="primary" icon="el-icon-s-fold" circle title="折叠" @click="datasetShow = !datasetShow"></el-button>
            </div>
          </div>
          <div class="panel-body" v-show="datasetShow">
            <!-- <dimension-tree v-if="currentSchema.dimension" :treeData="currentDimension" :options="dragOptions"></dimension-tree> -->
            <ul class="schema-tree" v-if="currentSchema.dimension">
              <span>
                <b>维度列(Dimension)</b>
              </span>
              <li>

                <draggable v-model="currentDimension" :group="{name: 'field',pull: true,put: false}" :sort="false" tag="ul"
                  @end="endDrag">
              <li v-for="(item, index) in currentDimension" :key="item.column + index">
                <span>
                  <i v-if="item.columns" class="schema-tree-icon hierarchy-icon"></i>
                  <i v-else class="schema-tree-icon blue-icon"></i>
                  {{ item.alias || item.column }}
                </span>
              </li>
              </draggable>
              </li>
            </ul>
            <measure-tree v-if="currentSchema.measure" :treeData="currentMeasure" :options="dragMeasureOptions"></measure-tree>

            <ul class="schema-tree" v-if="currentSchema.dimension" style="margin-top: 20px;">
              <span>
                <b>过滤器(Filters)</b>
                <i class="el-icon-circle-plus" style="cursor:pointer;margin-left:5px;font-size: 18px;" @click="filterOptAddOrUpdate('add',{})"></i>
              </span>
              <li>

                <draggable v-model="filters" :group="{name: 'filter',pull: true,put: false}" :sort="false" tag="ul">
                <li v-for="(item, index) in filters" :key="index">
                  <span>
                    <i class="schema-tree-icon blue-icon"></i>
                    {{ item.group }}
                    <input type="hidden" ref="timestamp" name="timestamp" :value="item.timestamp">
                    <input type="hidden" ref="filters" name="filters" :value="item.filters">
                    <i class="el-icon-edit-outline" style="margin-left: 5px;" @click="filterOptAddOrUpdate('update',item)"></i>
                    <i class="el-icon-delete" style="margin-left: 5px;" @click="filterItemDelHandle(index)"></i>
                  </span>
                </li>
              </draggable>
              </li>
            </ul>
          </div>

        </el-card>
      </el-col>

      <el-col :span="19" v-if="widgetConfigVisible">
        <el-card>
            <div class="box-header with-border">
              <h3 class="box-title" style="font-weight: bold">{{ currentNode.name }}</h3>
              <!-- <i class="pull-right el-icon-delete" @click="delWidget"></i> -->
            </div>

            <div class="box-body">
              <div class="el-form-item">
                <label class="el-form-item__label">数据源:</label>
                <div class="el-form-item__content">
                  <el-select v-model="datasetId" placeholder="请选择" class="select-axis" @change="datasetIdChangeHandle">
                    <el-option v-for="item in datasetList" :key="item.id" :label="item.name" :value="item.id">
                    </el-option>
                  </el-select>
                </div>
              </div>

              <!-- Widget Name -->
              <div class="el-form-item">
                <label class="el-form-item__label">图表名:</label>
                <div class="el-form-item__content">
                  <el-input v-model="currentNode.name" placeholder="Widget Name"></el-input>
                </div>
              </div>

              <!-- Widget Type -->
              <div class="el-form-item">
                <label class="el-form-item__label">图表类型:</label>
                <div class="el-form-item__content">
                  <ul class="widget-type-list">
                    <li v-for="(type, index) in widgetTypes" @click.prevent="handleTypeClick(type, index)">
                      <el-popover placement="bottom" trigger="hover">
                        <div>
                          <p><b>{{ type.row }} 行维</b></p>
                          <p><b>{{ type.column }} 列维</b></p>
                          <p><b>{{ type.measure }} 指标</b></p>
                        </div>
                        <i slot="reference" :class="[type.class, chartTypesStatus[type.value]?'':'disabled', index===activeTypeIndex?'active':'']"
                          class="widget-type-item"></i>
                      </el-popover>
                    </li>
                  </ul>
                </div>
              </div>

              <!-- Row: 对应 Widget.data.config.keys 的值 -->
              <div class="el-form-item">
                <label class="el-form-item__label">行维:</label>
                <div class="el-form-item__content" style="height: 42px;">
                  <draggable class="drop-input" v-model="row" :options="{group:'field'}" id="row" tag="ul">
                    <li v-for="(col, index) in row" :key="col.name + '_' + index" @click="removeDimension(index, 'row')"
                      class="moveable">
                      <span>
                        <i class="schema-tree-icon blue-icon"></i>
                        {{ col.alias || col.column || col.col }}
                      </span>
                    </li>
                  </draggable>
                </div>
              </div>

              <!-- Column: 对应 Widget.data.config.groups 的值 -->
              <div class="el-form-item">
                <label class="el-form-item__label">列维:</label>
                <div class="el-form-item__content" style="height: 42px;">
                  <draggable class="drop-input" v-model="column" :options="{group:'field'}" tag="ul" id="column">
                    <li v-for="(col, index) in column" :key="col.name + '_' + index" @click="removeDimension(index, 'col')"
                      class="moveable">
                      <span>
                        <i class="schema-tree-icon blue-icon"></i>
                        {{ col.alias || col.column || col.col }}
                      </span>
                    </li>
                  </draggable>
                </div>
              </div>

              <!-- Filter -->
              <div class="el-form-item">
                <label class="el-form-item__label">
                  过滤

                </label>
                <div class="el-form-item__content" style="height: 42px;">
                  <draggable class="drop-input" v-model="filterInput" :options="{group:'filter'}" id="column">
                    <span v-for="(item,index) in filterInput" :key="index">
                      <el-button-group style="margin: 3px;" v-if="item.group">
                        <el-button type="info" @click="filterHandle(item)">{{item.group}}</el-button>
                        <el-button type="info" icon="el-icon-edit-outline" @click="filterOptAddOrUpdate('update',item)"></el-button>
                      </el-button-group>
                    </span>
                  </draggable>
                </div>
                <!-- <div class="el-form-item__content">
                  <div class="drop-input filter-input">
                    <div v-for="(filter, index) in filterInput" :key="filter.id" class="filter-item">
                      <component class="filter-param" :is="getParamComponent(filter.param.paramType)" :param="filter.param"
                        :filterId="filter.key" :currentValue="filter.value"></component>
                      <i class="filter-del el-icon-delete" @click="removeFilterInput(index)"></i>
                    </div>
                  </div>
                </div> -->
              </div>
              <!-- Filter -->

              <!-- Value: 对应 Widget.data.config.values 的值 -->
              <!-- value -->
              <div class="el-form-item" v-if="axisValueType === 'normal'">
                <label class="el-form-item__label">指标:</label>
                <div class="el-form-item__content" style="height: 42px;">
                  <draggable class="drop-input" v-model="value[0].cols" :options="dragValueOptions" element="ul">
                    <li v-for="(col, index) in value[0].cols" :key="col.column" @click="removeMeasure(index)" class="moveable">
                      <span>
                        <i class="schema-tree-icon blue-icon"></i>
                        {{ col.col || col.column }}
                      </span>
                    </li>
                  </draggable>
                </div>
              </div>
              <!-- value -->

              <!-- value axis -->
              <div class="el-form-item" v-if="axisValueType === 'axis'">
                <label class="el-form-item__label">
                  Value Axis
                  <!-- <i class="el-icon-circle-plus" style="cursor:pointer;margin-left:2px;" @click="addValueAxis"></i> -->
                </label>
                <div class="el-form-item__content">

                  <div v-for="(axisValue, index) in value" :key="index">
                    <el-select v-model="axisValue.series_type" :class="['select-axis']" @change="seriesChangeHandle">
                      <el-option v-for="item in valueAxisOption" :label="item" :value="item" :key="item"></el-option>
                    </el-select>
                    <div class="drop-input drop-input-axis">
                      <draggable v-model="axisValue.cols" :options="dragValueOptions" element="ul">
                        <li v-for="(col, index) in axisValue.cols" :key="col.column" @click="removeAxisMeasure(index, axisValue.cols)"
                          class="moveable">
                          <span>
                            <i class="schema-tree-icon blue-icon"></i>
                            {{ col.col || col.column }}
                          </span>
                        </li>
                      </draggable>
                    </div>
                  </div>

                </div>
              </div>
              <!-- value axis -->


              <!-- <div class="el-form-item">
                <el-button type="primary" @click="save" size="small" class="pull-right" style="margin-right: 10px">Save</el-button>
                <el-button type="primary" @click="preview" size="small" class="pull-right" style="margin-right: 10px">Preview</el-button>
              </div> -->
            </div>
            <div style="height: 33px;margin-top: 10px;">
              <div style="float: right;">
                <el-button type="primary" class="button" @click="preview">预览</el-button>
                <el-button type="primary" class="button" @click="previewQuery">预览查询</el-button>
                <el-button type="success" class="button" @click="save">保存</el-button>
              </div>
            </div>

            <!-- 底部面板内容，包含 Preview 等 -->
            <div class="widget-config-tab">
              <el-tabs type="border-card" v-model="activeName" :tab-click="tabClickHandle">
                <el-tab-pane label="Preview" name="Preview">
                  <component v-if="isPreview" :is="currentPreview" :widget="currentPreviewWidget" :key="currentPreviewWidget.widget.id + currentPreviewWidget.widget.data.chart_type"></component>
                </el-tab-pane>
                <el-tab-pane label="Query" name="Query">
                  <el-input type="textarea" rows="10" v-model="querySql"></el-input>
                </el-tab-pane>
                <el-tab-pane label="Option" name="Option">
                  <component :is="currentOptionComponent" @apply-option="applyOption" @clear-option="clearOption"></component>
                  <!-- <bar-option @apply-option="applyOption"></bar-option> -->
                </el-tab-pane>
              </el-tabs>
            </div>

        </el-card>
      </el-col>
    </el-row>
    <!-- 弹窗，过滤器 -->
    <filter-opt v-if="optVisible" ref="optDialog" @refreshFilter="refreshParams"></filter-opt>
  </div>
</template>

<script>
  import {
    widgetList,
    getDataSetOne,
    delWidget,
    saveNewWidget,
    updateWidget,
    selectSql
  } from '@/api/cboard/cboard'
  import { injectFilter, formatConfig } from '@/util/dashboardConfig.js';

  import FilterOpt from '../components/FilterOpt'
  /***************************************
 Widget Type 对应的规则
 *  0:  None items
 *  1:  only 1 item
 * -1:  None Restrict
 *  2:  1 or more
 ***************************************/
  const configRule = {
    line: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    pie: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    kpi: {
      keys: 0,
      groups: 0,
      filters: -1,
      values: 1
    },
    table: {
      keys: -1,
      groups: -1,
      filters: -1,
      values: -1
    },
    funnel: {
      keys: -1,
      groups: 0,
      filters: -1,
      values: 2
    },
    sankey: {
      keys: 2,
      groups: 2,
      filters: -1,
      values: 1
    },
    radar: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    map: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    scatter: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    gauge: {
      keys: 0,
      groups: 0,
      filters: -1,
      values: 1
    },
    wordCloud: {
      keys: 2,
      groups: 0,
      filters: -1,
      values: 1
    },
    treeMap: {
      keys: 2,
      groups: 0,
      filters: -1,
      values: 1
    },
    areaMap: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 1
    },
    heatMapCalendar: {
      keys: 1,
      groups: 0,
      filters: -1,
      values: 1
    },
    heatMapTable: {
      keys: 2,
      groups: 2,
      filters: -1,
      values: 1
    },
    liquidFill: {
      keys: 0,
      groups: 0,
      filters: -1,
      values: 1
    },
    contrast: {
      keys: 2,
      groups: 0,
      filters: -1,
      values: 2
    },
    chinaMap: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    chinaMapBmap: {
      keys: 2,
      groups: -1,
      filters: -1,
      values: 2
    },
    relation: {
      keys: 2,
      groups: 2,
      filters: -1,
      values: 1
    }
  };

  const widgetTypeMap = {
    table: 'TableContent',
    line: 'ChartContent',
    pie: 'ChartContent',
    contrast: 'ChartContent',
    kpi: 'KpiContent',
    map: 'MapContent',
    radar: 'RadarContent',
    funnel: 'FunnelContent',
    chinaMap: 'ChinaMapContent',
    scatter: 'ScatterContent',
  }

  const optionMap = {
    line: 'BarOption',
    pie: 'PieOption',
    radar: 'RadarOption',
    contrast: 'ContrastOption',
    funnel: 'FunnelOption',
    kpi: 'KpiOption',
    scatter: 'ScatterOption',
  }

  const valueAxisOptionMap = {
    'line': ['line', 'bar'],
    'pie': ['pie', 'doughnut', 'coxcomb']
  }

  export default {
    name: 'WidgetConfig',
    components: {
      FilterOpt,
      // DimensionTree: () => import('@/components/widgetConfig/DimensionTree.vue'),
      MeasureTree: () => import('@/components/widgetConfig/MeasureTree.vue'),
      draggable: () => import('vuedraggable'),
      //---图表---
      KpiContent: () => import('@/components/dashboard/widgetsLei/KpiContent'),
      ChartContent: () => import('@/components/dashboard/widgetsLei/ChartContent'),
      TableContent: () => import('@/components/dashboard/widgetsLei/TableContent'),
      MapContent: () => import('@/components/dashboard/widgetsLei/MapContent'),
      RadarContent: () => import('@/components/dashboard/widgetsLei/RadarContent'), //雷达图
      FunnelContent: () => import('@/components/dashboard/widgetsLei/FunnelContent'), //漏斗图
      ScatterContent: () => import('@/components/dashboard/widgetsLei/ScatterContent'),
      ChinaMapContent: () => import('@/components/dashboard/widgetsLei/ChinaMapContent'),
      //---Filter---
      ParamSelector: () => import('@/components/dashboard/params/ParamSelector'),
      ParamSlider: () => import('@/components/dashboard/params/ParamSlider'),
      DatePicker: () => import('@/components/dashboard/params/DatePicker'),
      //---option---
      BarOption: () => import('@/components/config/options/BarOption'),
      PieOption: () => import('@/components/config/options/PieOption'),
      RadarOption: () => import('@/components/config/options/RadarOption'),
      ContrastOption: () => import('@/components/config/options/ContrastOption'),
      FunnelOption: () => import('@/components/config/options/FunnelOption'),
      KpiOption: () => import('@/components/config/options/KpiOption'),
      ScatterOption: () => import('@/components/config/options/ScatterOption'),
    },
    created() {
      this.$store.dispatch('config/getWidgetList');
      this.$store.dispatch('config/getDatasetList');
    },
    watch: {
      filterText(val) {
        this.$refs.tree.filter(val);
      }
    },
    data() {
      return {
        isShow: true,
        datasetShow: true,
        activeName: 'Preview',
        filterText: '',
        defaultProps: { // widget 目录配置
          label: 'name'
        },
        datasetId: '',
        currentNode: {}, // 点击 widget 目录，选中的 node（即当前选中的 Widget 对象）
        currentOption: {}, // option-样式配置
        activeTypeIndex: 0, // 当前选中的 Widget Type 索引
        widgetConfigVisible: false, // 配置面板是否显示
        column: [], // Column 的值
        row: [], // Row 的值
        filter: [], // Filter 的值
        value: [], // Value 的值
        isPreview: false, // 是否显示预览
        querySql: '',
        option: {
          value: {
            orient: ''
          }
        },
        orientOptions: ['horizontal', 'vertical'],
        // widget Type 列表
        widgetTypes: [{
            name: '表格',
            value: 'table',
            class: 'cTable',
            row: '0个或多个',
            column: '0个或多个',
            measure: '0个或多个'
          }, {
            name: '折线/柱状图',
            value: 'line',
            class: 'cLine',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '对比图',
            value: 'contrast',
            class: 'cContrast',
            row: '1个或多个',
            column: '0',
            measure: '1个或多个'
          },
          {
            name: '散点图/气泡图',
            value: 'scatter',
            class: 'cScatter',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '饼图',
            value: 'pie',
            class: 'cPie',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '指标卡',
            value: 'kpi',
            class: 'cKpi',
            row: '0',
            column: '0',
            measure: '1'
          },
          {
            name: '漏斗图',
            value: 'funnel',
            class: 'cFunnel',
            row: '0个或多个',
            column: '0',
            measure: '1个或多个'
          },
          {
            name: '桑基图',
            value: 'sankey',
            class: 'cSankey',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1'
          },
          {
            name: '雷达图',
            value: 'radar',
            class: 'cRadar',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '中国地图',
            value: 'map',
            class: 'cMap',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '计量图',
            value: 'gauge',
            class: 'cGauge',
            row: '0',
            column: '0',
            measure: '1'
          },
          {
            name: '标签云',
            value: 'wordCloud',
            class: 'cWordCloud',
            row: '1个或多个',
            column: '0',
            measure: '1'
          },
          {
            name: '矩形树图',
            value: 'treeMap',
            class: 'cTreeMap',
            row: '1个或多个',
            column: '0',
            measure: '1'
          },
          {
            name: '热点图（日历）',
            value: 'heatMapCalendar',
            class: 'cHeatMapCalendar',
            row: '1',
            column: '0',
            measure: '1'
          },
          {
            name: '热点图（表格）',
            value: 'heatMapTable',
            class: 'cHeatMapTable',
            row: '1个或多个',
            column: '1个或多个',
            measure: '1'
          },
          {
            name: '水球图',
            value: 'liquidFill',
            class: 'cLiquidFill',
            row: '0',
            column: '0',
            measure: '1'
          },
          {
            name: '区域地图',
            value: 'areaMap',
            class: 'cAreaMap',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1'
          },
          {
            name: '中国地图（本地）',
            value: 'chinaMap',
            class: 'cChinaMap',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '中国地图（百度）',
            value: 'chinaMapBmap',
            class: 'cChinaMapBmap',
            row: '1个或多个',
            column: '0个或多个',
            measure: '1个或多个'
          },
          {
            name: '关系图',
            value: 'relation',
            class: 'cRelation',
            row: '1个或2个',
            column: '1个或2个',
            measure: '1'
          },
        ],
        //用于判断哪些 Widget Type 可选（Base值）
        baseChartTypesStatus: {
          "line": true,
          "pie": true,
          "kpi": true,
          "table": true,
          "funnel": true,
          "sankey": true,
          "radar": true,
          "map": true,
          "scatter": true,
          "gauge": true,
          "wordCloud": true,
          "treeMap": true,
          "heatMapCalendar": true,
          "heatMapTable": true,
          "liquidFill": true,
          "areaMap": true,
          "contrast": true,
          "chinaMap": true,
          "chinaMapBmap": true,
          "relation": true
        },
        dragMeasureOptions: {
          animation: 0,
          group: {
            name: 'measureConfig',
            pull: 'clone'
          },
          sort: false
        },
        optVisible: false,
        //Filter 相关
        isFilterShow: false,
        filterData: [],
        selectedFilterData: [],
        filterInput: [],
        paramTypeValue: 'selector', //param type 值
        paramTypes: ['selector', 'slider', 'datePicker'], //param type 列表
      }
    },
    computed: {
      widgetList: {
        get(){
          return this.$store.state.config.widgetList;
        },
        set(newValue){
          return newValue
        }
      },
      datasetList() {
        return this.$store.state.config.datasetList;
      },
      // 将 widgetList 转换成 Widget el-tree 需要的数据格式 //
      treeData() {
        let widgetList = this.widgetList;
        let treeData = [];
        for (let i = 0; i < widgetList.length; i++) {
          let widget = widgetList[i];
          addToTree(widget.categoryName, widget)
        }

        function addToTree(categoryName, widget) {
          let nameArr = categoryName.split('/');
          let name;
          let i = 0;
          let arr = treeData;
          while (i < nameArr.length) {
            name = nameArr[i];
            let result = existInArr(name, arr);
            if (result) {
              arr = result.children;
              if (i === nameArr.length - 1) {
                result.children.push(widget);
              }
            } else {
              let treeItem = {
                name: name,
                children: []
              };
              arr.push(treeItem);
              arr = treeItem.children;
              if (i === nameArr.length - 1) {
                treeItem.children.push(widget);
              }
            }
            i++;
          }
        }

        function existInArr(name, arr) {
          for (let i = 0, l = arr.length; i < l; i++) {
            if (arr[i].name === name) {
              return arr[i];
            }
          }
          return false;
        }
        return treeData;
      },
      // 根据当前选中的 widget 的 datasetId，找到对应的 dataset 数据 //
      currentDataset: {
        get() {
          if (!this.currentNode.data) return null;
          let datasetId = this.currentNode.data.datasetId;
          let dataset;
          for (let i = 0; i < this.datasetList.length; i++) {
            if (this.datasetList[i].id == datasetId) {
              dataset = this.datasetList[i];
              break;
            }
          }
          return dataset;
        },
        set(newValue) {
          return newValue
        }
      },
      currentSchema: {
        get() {
          if (!this.currentDataset) return [];
          return this.currentDataset.data.schema;
        },
        set(newValue) {
          return newValue
        }
      },
      /* 过滤 Dimension Tree 的数据 */
      currentDimension: {
        get() {
          // 当前图表的列维、行维框中已有的 dimension 数据
          let currentArray = this.column.concat(this.row);
          // 所有的 dimension 数据
          let dimension = this.currentSchema.dimension;
          // 过滤后的 dimension 数据
          let currentDimensions = [];

          for (let i = 0; i < dimension.length; i++) {
            let item = copyObj(dimension[i]);
            if (!inCurrentArray(item)) {
              currentDimensions.push(item) // --- 放回维度列
            }

            if (dimension[i].columns) {
              item.columns = [];
              let columns = dimension[i].columns;
              for (let j = 0, len = columns.length; j < len; j++) {
                if (!inCurrentArray(columns[j])) {
                  let o = copyObj(columns[j]);

                  if (item.type === 'level') { // 设置 level 字段
                    o.level = item.alias;
                  }

                  // 设置一些必须字段的默认值
                  o.col = o.column;
                  o.type = 'eq';
                  o.values = [];
                  o.sort = 'asc';

                  item.columns.push(o);
                }
              }
            }
          }

          function copyObj(obj) {
            let newObj = {};
            for (let p in obj) {
              newObj[p] = obj[p];
            }
            return newObj;
          }

          function inCurrentArray(obj) {
            for (let i = 0; i < currentArray.length; i++) {
              if (currentArray[i].col) {
                if (currentArray[i].col == obj.column) {
                  return true;
                }
              } else {
                if (currentArray[i].column == obj.column) {
                  return true;
                }
              }

            }
            return false;
          }
          return currentDimensions;
        },
        set(newValue) {
          return newValue;
        }
      },
      /*
        //过滤 Measure Tree 的数据
        (Measure Tree 不过滤，因为 value 值有时可以重复，如 line+bar 图的情况)
      */
      currentMeasure: {
        get() {
          let measure = this.currentSchema.measure;
          return measure;
        },
        set(newValue) {
          return newValue
        }

      },
      /*
        根据选中的 widget 数据，
        判断哪些 Widget Type 可选
      */
      chartTypesStatus() {
        if (!this.currentNode.data) {
          return {};
        }
        let result;
        let tempConfig = {
          keys: this.row.length,
          groups: this.column.length,
          values: 0
        }
        for (let type in this.baseChartTypesStatus) {
          let rule = configRule[type];
          // 计算 value 的长度
          let length = 0;
          this.value.forEach(v => {
            v.cols.forEach(c => {
              length++;
            });
          });
          tempConfig.values = length;

          for (let p in rule) {
            if (rule[p] === 2) {
              result = (tempConfig[p] >= 1);
            } else if (rule[p] === -1) {
              result = true;
            } else {
              result = (rule[p] === tempConfig[p]);
            }
            if (!result) break;
          }

          this.baseChartTypesStatus[type] = result;
        }

        return this.baseChartTypesStatus;
      },
      // 当前选中的 widget 配置数据
      currentWidgetConfig() {
        //this.isPreview = false;
        let config = {};

        // 图表水平or垂直显示，用于 bar 图
        if (this.currentNode.data.config.valueAxis !== undefined) config.valueAxis = this.currentNode.data.config.valueAxis;

        // 设置 widgetType
        let type = this.widgetTypes[this.activeTypeIndex];
        config.chart_type = type.value;

        // 设置 keys（对应 Row 的值）
        config.keys = this.row;

        // 设置 groups（对应 Column 的值）
        config.groups = this.column;

        // 设置 option
        config.option = this.currentOption;

        /*filters 格式：
        [
          {
            col: 'SALES_COUNTRY',
            type: '=',
            values: ['Mexico']
          }
        ]*/
        // TODO: filterInput 的数据转成 this.filters 格式，发现 filterInput 的数据格式有很多冗余和不合理，需要后续处理
        let filters = [];

        config.filters = this.filterInput;

        // 设置 values（对应 value 的值）
        for (let i = this.value.length - 1; i >= 0; i--) {
          this.value[i].cols.forEach(c => {
            if (!c.aggregate_type) c.aggregate_type = 'sum'; // 必须要有字段 aggregate_type，默认 'sum'
            if (!c.col) c.col = c.column; //必须要有个 col 字段记录名称，否则返回回的数据 columnList 中对应的 name 为 null
          })
        }

        config.values = this.value;

        return config;
      },
      // 当前预览的组件名
      currentPreview() {
        let type = this.widgetTypes[this.activeTypeIndex].value;
        return widgetTypeMap[type] ? widgetTypeMap[type] : 'ChartContent';
      },
      // 当前预览的组件数据
      currentPreviewWidget: {
        get() {
          let widget = {
            name: ''
          }

          let widgetData = {
            name: this.currentNode.name,
            categoryName: this.currentNode.categoryName,
            data: this.currentNode.data,
            id: this.currentNode.id
          };
          widgetData.data.config = this.currentWidgetConfig;
          widgetData.data.datasource = JSON.parse(this.dataSet.data).datasource
          widgetData.data.query = JSON.parse(this.dataSet.data).query.sql

          widget.widget = widgetData;
          return widget;
        },
        set(newValue) {
          return newValue
        }

      },
      // Filters
      filters() {
        // 当前图表的过滤框中已有的 filter 数据
        let currentArray = this.filter;
        // 所有的 dimension 数据
        let filter = this.currentDataset.data.filters;
        // 过滤后的 dimension 数据
        let currentDimensions = [];



        function expAndFilterLink(targetList, expList) {
          let arrList = []
          let collList = []
          for (let i = 0; i < targetList.length; i++) {
            collList.push(targetList[i]);
          }
          if(collList.length){
            for (let i = 0; i < expList.length; i++) {
              for (let j = 0; j < collList.length; j++) {
                if (expList[i].timestamp == collList[j].timestamp) {
                  break;
                }
                if (j == collList.length - 1) {
                  arrList.push(expList[i])
                }
              }
            }
          }else{
            arrList = expList
          }

          return arrList;
        }
        currentDimensions = expAndFilterLink(currentArray,filter)
        return currentDimensions;
      },
      // value 输入框的类型
      axisValueType() {
        let type = this.widgetTypes[this.activeTypeIndex];
        switch (type.value) {
          case 'line':
          case 'pie':
            return 'axis';
          default:
            return 'normal';
        }
      },
      // 当为 value axis 类型的输入框时，对应下拉框的内容
      valueAxisOption() {
        let type = this.widgetTypes[this.activeTypeIndex];
        return valueAxisOptionMap[type.value];
      },
      currentOptionComponent() {
        let type = this.widgetTypes[this.activeTypeIndex].value;
        return optionMap[type] ? optionMap[type] : '';
      },
      // 拖拽配置
      dragOptions() {
        return {
          animation: 0,
          group: 'dimensionConfig',
          sort: false
        };
      },
      dragValueOptions() {
        return {
          animation: 0,
          group: {
            name: 'measureConfig',
          },
        };
      }
    },
    methods: {
      // 删除图表
      deleteReset() {
        let name = this.currentNode.name;
        this.$confirm('是否确认删除名称为' + name, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(function() {
          return delWidget(name)
        }).then(data => {
          this.$message.success('删除成功')
          // this.searchReset();
          // this.getWidgetCategoryList();
          // this.getWidgetList();
          this.$store.dispatch('config/getWidgetList');
          this.addWidget()
        })
      },
      // 树结构查询事件
      filterNode(value, data) {
        if (!value) return true;
        return data.name.indexOf(value) !== -1;
      },
      // 点击选中图表
      handleNodeClick(node) {
        if (node.children && node.children.length > 0) {
          return;
        } else {
          this.widgetConfigVisible = true;
          this.currentNode = node;
          this.datasetId = node.data.datasetId

          this.currentOption = node.data.config.option || {};
          this.column = node.data.config.groups;
          this.row = node.data.config.keys;
          this.filter = node.data.config.filters
          this.value = node.data.config.values;
          if (this.value.length === 0) { //防止undefined报错的处理
            this.value.push({
              cols: []
            })
          }
          getDataSetOne(this.datasetId).then(response => {
            this.dataSet = response.data
            this.query = JSON.parse(this.dataSet.data).query.sql
          })

          // 根据图表类型获得索引，根据索引展示 widget type
          let index = this.getIndexByType(node.data.config.chart_type);
          this.activeTypeIndex = index;
          let type = this.widgetTypes[this.activeTypeIndex];
        }
      },
      getIndexByType(type) {
        for (let i = 0, l = this.widgetTypes.length; i < l; i++) {
          if (this.widgetTypes[i].value === type) {
            return i;
          }
        }
        return 0;
      },
      addWidget() {
        this.widgetConfigVisible = true;

        this.activeTypeIndex = 0;
        this.currentNode = {
          name: '',
          categoryName: '',
          data: {
            config: {

            },
            datasetId: '',
            expressions: [],
            filterGroups: []
          }
        };
        this.currentNode.data.config = {
          "option": {},
          "chart_type": "",
          "keys": [],
          "groups": [],
          "values": [{
            "name": "",
            "cols": []
          }],
          "filters": []
        }

        this.column = this.currentNode.data.config.groups;
        this.row = this.currentNode.data.config.keys;
        //this.value = this.currentNode.data.config.values;
        this.value = [{
          cols: [],
          name: '',
          series_type: ''
        }]
      },
      handleTypeClick(type, index) {
        let typeValue = type.value;
        if (!this.chartTypesStatus[typeValue]) {
          return false;
        }
        this.activeTypeIndex = index;

        // value axis 切换到 value 时，currentValue 数据格式的处理
        if (this.axisValueType === 'normal') {
          for (let i = this.value.length - 1; i >= 0; i--) {
            let item = this.value[i];
            if (i > 0) {
              this.value[0].cols = this.value[0].cols.concat(item.cols);
              this.value.splice(i, 1);
            }
          }
        }

        /*
          切换 widgetType，碰到有 Value Axis 的表单时，初始化下拉框的默认值
        */
        this.value.forEach(v => {
          if (this.valueAxisOption) {
            let inArr = false;
            this.valueAxisOption.forEach(option => {
              if (option === v.series_type) {
                inArr = true;
              }
            })
            if (!inArr) {
              v.series_type = this.valueAxisOption[0];
            }
          }
        })

      },
      seriesChangeHandle(val) {
        this.$set(this.value[0], 'series_type', val)
        this.value = [...this.value]
        this.currentPreviewWidget = { ...this.currentPreviewWidget
        }
      },
      // delWidget() {
      //   this.$confirm('是否删除该 Widget?', '提示', {
      //     confirmButtonText: '确定',
      //     cancelButtonText: '取消',
      //     type: 'warning',
      //     closeOnClickModal: false,
      //     customClass: 'preview-config-modal'
      //   }).then(() => {
      //     let params = {
      //       id: this.currentNode.id
      //     }
      //     this.$req.post(this.$api.deleteWidget, params)
      //       .then(response => {
      //         if (response.statusText === 'OK') {
      //           this.$message({
      //             type: 'success',
      //             message: '删除成功!'
      //           });
      //           this.widgetConfigVisible = false;
      //           this.$store.dispatch('config/getWidgetList');
      //         }
      //       })
      //       .catch(error => {})
      //   }).catch(() => {

      //   });
      // },
      removeDimension(index, type) {
        if (type === 'col') {
          this.column.splice(index, 1);
        } else if (type === 'row') {
          this.row.splice(index, 1);
        }
      },
      removeMeasure(index) {
        this.value[0].cols.splice(index, 1);
      },
      removeAxisMeasure(index, data) {
        data.splice(index, 1);
      },
      datasetIdChangeHandle(val) {
        getDataSetOne(val).then(response => {
          this.currentNode.data.datasetId = val
        })
      },
      tabClickHandle(tab) {
        if (tab.name == 'Preview') {
          this.currentPreviewWidget = {...this.currentPreviewWidget}
        }
      },

      addValueAxis() {
        if (this.value.length >= this.valueAxisOption.length) return;
        let valueAxisItem = {
          cols: [],
          name: '',
          series_type: this.valueAxisOption[0]
        }
        this.value.push(valueAxisItem);
      },
      save() {
        if (!this.currentNode.data.datasetId) return; //防止未选择 Cube 就提交

        let widgetData = {
          name: this.currentNode.name,
          categoryName: this.currentNode.categoryName,
          data: this.currentNode.data,
          id: this.currentNode.id
        };
        widgetData.data.config = this.currentWidgetConfig;
        if (widgetData.categoryName === '') widgetData.categoryName = 'Default Category';
        if (widgetData.data.datasetId === '') widgetData.data.datasetId = this.currentDataset.id;

        // values 的成员中，cols 没有值则删去该 values 成员
        let values = widgetData.data.config.values;
        for (let i = values.length - 1; i >= 0; i--) {
          if (values[i].cols.length === 0) values.splice(i, 1);
        }
        let params = {
          mapStr: JSON.stringify(widgetData)
        }
        if (widgetData.id) {
          updateWidget(params).then(response => {
            this.$message({
              type: 'success',
              message: '更新成功!'
            });
          })
        } else {
          saveNewWidget(params).then(response => {
            this.$message({
              type: 'success',
              message: '保存成功!'
            });
            this.$store.dispatch('config/getWidgetList');
          })
        }
      },
      preview() {
        this.activeName = 'Preview'
        this.isPreview = true;
      },
      previewQuery(){
        this.activeName = 'Query'
        let widgetData = this.currentPreviewWidget.widget.data
        let filters = this.currentPreviewWidget.widget.data.filters;
        injectFilter(widgetData, filters);
        const config = formatConfig(widgetData.config);

        let params = {
          datasourceId: widgetData.datasource,
          query: widgetData.query,
          datasetId: widgetData.datasetId,
          cfg: config,
          reload: false
        };
        selectSql({
          mapStr: JSON.stringify(params)
        }).then(response => {
          this.querySql = response.data;
        })
      },
      applyOption(option) {
        for (let prop in option) {
          //this.currentOption[prop] = option[prop];
          if (!this.currentOption[prop]) this.currentOption[prop] = {};
          if (typeof option[prop] === 'object') {
            for (let p in option[prop]) {
              if (option[prop][p] !== '') this.currentOption[prop][p] = option[prop][p];
            }
          }
        }
        this.$message({
          type: 'success',
          message: '应用成功！可切换到预览查看'
        });
      },
      clearOption(option) {
        for (let prop in option) {
          this.currentOption[prop] = option[prop];
        }
        this.$message({
          type: 'success',
          message: '清除成功！可切换到预览查看'
        });
      },
      endDrag(evt) {
        let name = evt.clone.textContent.trim()
        if (evt.to.id === 'column') {
          let code = this.column.slice(-1) || 0
          this.column[evt.newIndex] = {
            type: '=',
            col: name,
            sort: 'asc',
            id: '',
            values: []
          }
          this.column = [...this.column]
        } else if (evt.to.id === 'row') {
          let code = this.row.slice(-1) || 0
          this.row[evt.newIndex] = {
            type: '=',
            col: name,
            sort: 'asc',
            id: '',
            values: []
          }
          this.row = [...this.row]
        }
      },
      filterOptAddOrUpdate(type,data){
        let list = this.currentSchema.dimension
        this.optVisible = true
        this.$nextTick(() => {
          this.$refs.optDialog.init(type, this.datasetId, data, list)
        })
      },
      refreshParams(data){
        if(data.type == 'update'){
          this.filters.forEach((item,index) => {
            if(item.timestamp == data.data.timestamp){
              this.filters[index] = data.data
            }
          })
        }else{
          this.filters.push(data)
        }
      },
      filterItemDelHandle(index){
        this.filters.splice(index, 1)
      },
    }
  }
</script>

<style scoped>
  .pull-right {
    float: right;
  }
  .search {
    margin-bottom: 10px;
  }

  .el-card__body {
    padding: 0 !important;
  }

  .box-header>.box-tools {
    top: 11px !important;
  }

  .box-primary .box-header>.box-tools {
    top: 5px !important;
  }

  .panel-body {
    padding: 10px 20px;
    font-size: 13px;
  }

  .box-tools>i {
    font-size: 16px;
    cursor: pointer;
  }

  .box-header .el-icon-delete {
    font-size: 20px;
    font-weight: bold;
    cursor: pointer;
  }

  /*表单样式*/
  .el-form-item__label {
    font-weight: bold;
    width: 130px;
  }

  .el-form-item__content {
    overflow: hidden;
  }

  .widget-type-list {
    padding: 0;
    margin: 0;
  }

  .widget-type-list>li {
    display: inline-block;
    padding-right: 5px;
    padding-left: 5px;
  }

  .widget-type-list>li .widget-type-item {
    display: block;
    width: 40px;
    height: 40px;
    cursor: pointer;
  }

  .widget-type-list>li .widget-type-item.active {
    border: 1px solid #97b6f7;
  }

  li:focus,
  i:focus,
  span:focus {
    outline: none;
  }

  /*######### Widget Type Icon 样式 ##############*/
  .cLine {
    background-image: url(../../../const/cboard/widgets/line-active.png);
  }

  .cLine.disabled {
    background-image: url(../../../const/cboard/widgets/line.png);
  }

  .cContrast {
    background-image: url(../../../const/cboard/widgets/contrast-active.png);
  }

  .cContrast.disabled {
    background-image: url(../../../const/cboard/widgets/contrast.png);
  }

  /*.cBar{  background-image: url(../imgs/bar-active.png);  }*/
  /*.cBar.disabled{background-image: url(../imgs/bar.png);  }*/
  .cScatter {
    background-image: url(../../../const/cboard/widgets/scatter-active.png);
  }

  .cScatter.disabled {
    background-image: url(../../../const/cboard/widgets/scatter.png);
  }

  .cPie {
    background-image: url(../../../const/cboard/widgets/pie-active.png);
  }

  .cPie.disabled {
    background-image: url(../../../const/cboard/widgets/pie.png);
  }

  .cFunnel {
    background-image: url(../../../const/cboard/widgets/funnel-active.png);
  }

  .cFunnel.disabled {
    background-image: url(../../../const/cboard/widgets/funnel.png);
  }

  .cKpi {
    background-image: url(../../../const/cboard/widgets/kpi-active.png);
  }

  .cKpi.disabled {
    background-image: url(../../../const/cboard/widgets/kpi.png);
  }

  .cSankey {
    background-image: url(../../../const/cboard/widgets/sankey-active.png);
  }

  .cSankey.disabled {
    background-image: url(../../../const/cboard/widgets/sankey.png);
  }

  .cRadar {
    background-image: url(../../../const/cboard/widgets/radar-active.png);
  }

  .cRadar.disabled {
    background-image: url(../../../const/cboard/widgets/radar.png);
  }

  .cTable {
    background-image: url(../../../const/cboard/widgets/table-active.png);
  }

  .cTable.disabled {
    background-image: url(../../../const/cboard/widgets/table.png);
  }

  .cMap {
    background-image: url(../../../const/cboard/widgets/map-active.png);
  }

  .cMap.disabled {
    background-image: url(../../../const/cboard/widgets/map.png);
  }

  .cGauge {
    background-image: url(../../../const/cboard/widgets/gauge-active.png);
  }

  .cGauge.disabled {
    background-image: url(../../../const/cboard/widgets/gauge.png);
  }

  .cWordCloud {
    background-image: url(../../../const/cboard/widgets/wordCloud-active.png);
  }

  .cWordCloud.disabled {
    background-image: url(../../../const/cboard/widgets/wordCloud.png);
  }

  .cTreeMap {
    background-image: url(../../../const/cboard/widgets/treeMap-active.png);
  }

  .cTreeMap.disabled {
    background-image: url(../../../const/cboard/widgets/treeMap.png);
  }

  .cAreaMap {
    background-image: url(../../../const/cboard/widgets/areaMap-active.png);
  }

  .cAreaMap.disabled {
    background-image: url(../../../const/cboard/widgets/areaMap.png);
  }

  .cHeatMapCalendar {
    background-image: url(../../../const/cboard/widgets/heatMapCalendar-active.png);
  }

  .cHeatMapCalendar.disabled {
    background-image: url(../../../const/cboard/widgets/heatMapCalendar.png);
  }

  .cHeatMapTable {
    background-image: url(../../../const/cboard/widgets/heatMapTable-active.png);
  }

  .cHeatMapTable.disabled {
    background-image: url(../../../const/cboard/widgets/heatMapTable.png);
  }

  .cLiquidFill {
    background-image: url(../../../const/cboard/widgets/liquidFill-active.png);
  }

  .cLiquidFill.disabled {
    background-image: url(../../../const/cboard/widgets/liquidFill.png);
  }

  .cChinaMap {
    background-image: url(../../../const/cboard/widgets/chinaMap-active.png);
  }

  .cChinaMap.disabled {
    background-image: url(../../../const/cboard/widgets/chinaMap.png);
  }

  .cChinaMapBmap {
    background-image: url(../../../const/cboard/widgets/chinaMapBmap-active.png);
  }

  .cChinaMapBmap.disabled {
    background-image: url(../../../const/cboard/widgets/chinaMapBmap.png);
  }

  .cRelation {
    background-image: url(../../../const/cboard/widgets/relation-active.png);
  }

  .cRelation.disabled {
    background-image: url(../../../const/cboard/widgets/relation.png);
  }

  .el-form-item {
    margin-bottom: 5px;
  }

  .drop-input {
    display: inline-block;
    width: 100%;
    height: 40px;
    line-height: 40px;
    background-color: #fff;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    margin: 0;
    padding: 0 10px;
    box-sizing: border-box;
  }

  .drop-input.active {
    border-color: #3c8dbc;
  }

  .filter-input {
    min-height: 40px;
    height: auto;
  }

  .drop-input li {
    display: inline-block;
    height: 28px;
    line-height: 28px;
    margin: 0 5px;
    padding: 0 8px;
    border: 1px solid #d9e3ec;
    border-radius: 2px;
    list-style-type: none;
    box-sizing: border-box;
    background-color: #fbfcfd;
    cursor: pointer;
  }

  .drop-input-axis {
    display: block;
    overflow: hidden;
    width: auto;
  }

  .drop-input-axis ul {
    height: 100%;
    margin: 0;
    padding: 0;
  }

  .select-axis {
    float: left;
    width: 150px;
  }

  .widget-config-tab .el-tabs {
    box-shadow: none;
    border: none;
    border-top: 1px solid #dcdfe6;
  }

  /*Filter 弹出窗相关*/
  .filter-config-dialog .row {
    margin-bottom: 15px;
  }

  .filter-item {
    float: left;
    font-size: 0px;
    line-height: normal;
    margin-right: 10px;
  }

  .filter-item .filter-param {
    display: inline-block;
    line-height: normal;
    margin-top: 6px;
    font-size: 12px;
    vertical-align: middle;
  }

  /*filter 删除按钮*/
  .filter-item .filter-del {
    display: inline-block;
    line-height: normal;
    margin-top: 6px;
    height: 28px;
    line-height: 28px;
    font-size: 12px;
    vertical-align: middle;
    border-top: 1px solid #dcdfe6;
    border-bottom: 1px solid #dcdfe6;
    border-right: 1px solid #dcdfe6;
    border-radius: 2px;
    width: 18px;
    text-align: center;
    color: #555;
    cursor: pointer;
  }

  .el-date-editor {
    background-color: red;
  }
</style>

<style scoped>
  .el-tabs--border-card>.el-tabs__content {
    padding: 0 !important;
  }

  .schema-tree {
    overflow: hidden;
  }

  .schema-tree li {
    position: relative;
    list-style-type: none;
    margin: 0;
    white-space: nowrap;
    padding-left: 15px;
  }

  .schema-tree li:before,
  .schema-tree li:after {
    content: '';
    position: absolute;
  }

  .schema-tree li:before {
    top: 0;
    left: -5px;
    height: 100%;
    width: 1px;
    border-left: 1px dotted black;
  }

  .schema-tree li:after {
    top: 9px;
    left: -5px;
    height: 100%;
    width: 15px;
    border-top: 1px dotted black;
  }

  .schema-tree li:last-child:before {
    height: 11px;
  }

  .moveable {
    cursor: move;
  }

  .schema-tree-icon {
    display: inline-block;
    vertical-align: middle;
    width: 15px;
    height: 15px;
  }

  .blue-icon {
    background: url(../../../const/cboard/bullet_blue.png);
  }

  .fa-trash-o {
    cursor: pointer;
  }
</style>
